/*
 * tcpipsim.c
 *
 *  Created on: 2009-4-15
 *      Author: tian
 */

#include"tcpipsim.h"
#include<sys/types.h>
#include<errno.h>
#include<stdio.h>

#define NOTEST

#ifdef NOTEST


void* do_timer_thread_handler(){
	timer_thread_handler();
	return NULL;
}

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
int main(){
	pthread_t thread_id;
	if(init()<0){
		fprintf(stderr,"ERROR:cannot initialize tcp/ip stack\n");
		return -1;
	}
	if((pthread_create(&thread_id,NULL,&do_timer_thread_handler,NULL))<0){
		perror("cannot create thread");
		return -1;
	}
	network_thread_handler(my_msgqid);
	return 0;
}
#endif

#ifdef TEST_IPADDR
int main(){
	if(init()<0){
			fprintf(stderr,"ERROR:cannot initialize tcp/ip stack\n");
			return -1;
	}
	printf("\n\nAfter init():\n");
	int i=0;
	for(i=0;i<4;i++){
		printf("%d.",my_ip_addr.part[i]);
	}
	printf("**************");
	printf("change to string\n");
	printf("%s\n",inet_ntoa(my_ip_addr));
	return 0;
}

#endif


#ifdef TEST_IP
#include<string.h>
int main(int argc,char **argv){
	if(argc!=2){
		printf("Usage:%s server/client\n",argv[0]);
		return -1;
	}
	struct iphdr hd;
	char buf[2]={'a',0};
	int rv=0;
	msg data;
	memset(&data,0,sizeof(data));
	memset(&hd,0,sizeof(hd));
	if(init()<0){
		fprintf(stderr,"ERROR:cannot initialize tcp/ip stack\n");
		return -1;
	}
	if(strcmp(argv[1],"server")==0){
		if((rv=msgrcv(my_msgqid,&data,sizeof(msg)-sizeof(long),0,0))<0){
			perror("Error in msgrcv");
			return -1;
		}
		if(data.mtype==MSG_IP_TUNNEL)
			ip_input(data.buf);
		else{
			fprintf(stderr,"ERROR:not a ip package");
		}
	}
	else if(strcmp(argv[1],"client")==0){
		//hd.des=routelst[0].ip_addr;
		inet_aton("192.168.0.1",&hd.des);
		hd.src=my_ip_addr;
		hd.ip_id.ip_id=DEFAULT_ID;
		hd.ip_verhl.ip_len=DEFAULT_IP_HEADER_LENGTH/8+1;
		hd.ip_pro=PROTOCOL_TCP;
		hd.ip_verhl.ip_tos=DEFAULT_TOS;
		hd.ip_ttl=DEFAULT_TTL;
		hd.ip_sum=0;
		hd.ip_verhl.ip_hl=DEFAULT_IP_HEADER_LENGTH/16;
		hd.ip_verhl.ip_ver=DEFAULT_IP_VERSION;
		ip_output(&hd,buf,1);
	}
	else{
		printf("Usage:%s server/client\n",argv[0]);
		return -1;
	}

	return 0;
}
#endif

#ifdef TESTTCP
int main(int argc,char **argv){
	if(argc!=2){
		printf("Usage:%s server/client\n",argv[0]);
		return -1;
	}
	struct iphdr hd;
	int rv=0;
	msg data;
	struct sockaddr addr;
	memset(&data,0,sizeof(data));
	memset(&hd,0,sizeof(hd));
	memset(&addr,0,sizeof(struct sockaddr));
	if(init()<0){
		fprintf(stderr,"ERROR:cannot initialize tcp/ip stack\n");
		return -1;
	}
	if(strcmp(argv[1],"server")==0){
		addr.my_ip=my_ip_addr;
		addr.my_port=1000;
		//fprintf(stderr,"state:%d\n",ptcpcb->tcp_state);
		struct tcpcb* ptcpcb=tcp_new_tcpcb(0,1,TCP_LISTEN,&addr,0);
		ptcpcb->q2num=3;
		ptcpcb->q2beg=0;
		ptcpcb->q2end=0;
		ptcpcb->queue2=malloc(sizeof(struct sockaddr)*ptcpcb->q2num);
		if(ptcpcb==NULL){
			fprintf(stderr,"ptcpcb is null in main\n");
			return -1;
		}
		fprintf(stderr,"state:%d\n",ptcpcb->tcp_state);
		while(1){
			if((rv=msgrcv(my_msgqid,&data,sizeof(msg)-sizeof(long),0,0))<0){
				perror("Error in msgrcv");
				return -1;
			}
			if(data.mtype==MSG_IP_TUNNEL)
				ip_input(data.buf);
			else{
				fprintf(stderr,"ERROR:not a ip package");
			}
		}
	}
	else if(strcmp(argv[1],"client")==0){
		//hd.des=routelst[0].ip_addr;
		inet_aton("192.168.0.1",&hd.des);
		addr.my_ip=my_ip_addr;
		addr.my_port=2000;
		addr.peer_ip=hd.des;
		addr.peer_port=1000;
		struct tcpcb *ptcpcb=tcp_new_tcpcb(0,1,TCP_CLOSED,&addr,0);
		struct tcphdr th;
		memset(&th,0,sizeof(struct tcphdr));
		struct ip_fake_hdr ipfhdr;
		th.tcp_sport=addr.my_port;
		th.tcp_dport=addr.peer_port;
		fprintf(stderr,"state:%d\n",ptcpcb->tcp_state);
		tcp_input(NULL,NULL,ptcpcb,active_open);
		fprintf(stderr,"state:%d\n",ptcpcb->tcp_state);
		/*get ack*/
		if((rv=msgrcv(my_msgqid,&data,sizeof(msg)-sizeof(long),0,0))<0){
					perror("Error in msgrcv");
					return -1;
		}
		if(data.mtype==MSG_IP_TUNNEL)
			ip_input(data.buf);
		else{
			fprintf(stderr,"ERROR:not a ip package");
		}
		fprintf(stderr,"state:%d\n",ptcpcb->tcp_state);
		ptcpcb->sndbuf[0]='a';
		ptcpcb->sndlen=1;
		tcp_input(NULL,NULL,ptcpcb,send_data);
		if((rv=msgrcv(my_msgqid,&data,sizeof(msg)-sizeof(long),0,0))<0){
			perror("Error in msgrcv");
			return -1;
		}
		if(data.mtype==MSG_IP_TUNNEL)
			ip_input(data.buf);
		else{
			fprintf(stderr,"ERROR:not a ip package");
		}
		tcp_input(NULL,NULL,ptcpcb,close_sock);
		fprintf(stderr,"after close state:%d\n",ptcpcb->tcp_state);
	}
	else{
		printf("Usage:%s server/client\n",argv[0]);
		return -1;
	}

	return 0;
}
#endif
#ifdef TCPCHECKSUM
int main(){
	struct tcphdr th;
	memset(&th,0,sizeof(th));
	th.tcp_dport=1025;
	th.tcp_sport=9877;
	th.tcp_hl_flag.syn=1;
	struct ip_fake_hdr ifhdr;
	inet_aton("192.168.0.1",&ifhdr.des);
	inet_aton("192.168.0.2",&ifhdr.src);
	ifhdr.mbz=0;
	ifhdr.pro=6;
	ifhdr.tcp_l=20;
	th.tcp_sum=tcp_checksum(&ifhdr,&th);
	printf("unsh:%d\n",sizeof(ifhdr));
	printf("sport:%d,dport:%d,",th.tcp_sport,th.tcp_dport);
	printf("sum:%d,seq:%ld,ack:%ld\n",th.tcp_sum,th.tcp_seq,th.tcp_ack);
	printf("check sum in recieve:%d\n",tcp_checksum(&ifhdr,&th));
	return 0;
}
#endif
